﻿using System;
using System.Data;
using System.Collections.Generic;
using Microsoft.SqlServer.Management.Smo;
using CoNatural.Data.VisualStudio.AddIn.Helpers;

namespace CoNatural.Data.VisualStudio.AddIn.Tools {
	/// <summary>
	/// Table field template
	/// </summary>
	[Serializable]
	public class Field {
		public string Name { get; internal set; }
		public string TypeName { get; internal set; }
		public bool IsNullable { get; internal set; }
		public bool IsReadOnly { get; internal set; }
		public bool InPrimaryKey { get; internal set; }
		public int Size { get; internal set; }		
		public string PropertyName { get; internal set; }
		public string PropertyTypeName { get; internal set; }
		public string PropertyInAttribute { get; internal set; }
		public string PropertyOutAttribute { get; internal set; }
	}

	/// <summary>
	/// Stored procedure parameter template
	/// </summary>
	[Serializable]
	public class Parameter {
		public string Name { get; internal set; }
		public string TypeName { get; internal set; }
		public ParameterDirection Direction { get; internal set; }
		public string PropertyName { get; internal set; }
		public string PropertyTypeName { get; internal set; }
		public string PropertyAttribute { get; internal set; }
	}

	[Serializable]
	public class TemplateHost : TextTemplatingEngineHostBase {
		public string Schema { get; private set; }

		// table template
		public bool IsTable { get; private set; }
		public string Table { get; private set; }
		public int IdentityIndex { get; private set; }
		public Field[] Fields { get; private set; }

		// stored procedure template
		public bool IsStoredProcedure { get; private set; }
		public string StoredProcedure { get; private set; }
		public string SqlScript { get; private set; }
		public Parameter[] Parameters { get; private set; }

		internal TemplateHost(Table table, string _namespace, string name) {
			Namespace = _namespace;
			Name = name;

			Schema = table.Schema;
			IsTable = true;
			Table = table.Name;
			IdentityIndex = -1;

			int colCount = table.Columns.Count;
			Fields = new Field[colCount];
			for (int i = 0; i < colCount; i++) {
				Fields[i] = new Field();
				Column col = table.Columns[i];

				if(col.Identity)
					IdentityIndex = i;

				Fields[i].Name = col.Name;
				Fields[i].TypeName = col.DataType.Name;
				Fields[i].IsNullable = col.Nullable;
				Fields[i].IsReadOnly = col.Computed;
				Fields[i].InPrimaryKey = col.InPrimaryKey;

				var ph = PropertyHelper.CreatePropertyHelper(table.Parent, col.Name, col.DataType, col.Nullable, ParameterDirection.Input);
				Fields[i].Size = ph.Size;
				Fields[i].PropertyName = ph.Name;
				Fields[i].PropertyTypeName = ph.TypeName;
				Fields[i].PropertyInAttribute = ph.Attribute;
				ph = PropertyHelper.CreatePropertyHelper(table.Parent, col.Name, col.DataType, col.Nullable, ParameterDirection.Output);
				Fields[i].PropertyOutAttribute = ph.Attribute;
			}
		}

		internal TemplateHost(StoredProcedure procedure, string _namespace, string name) {
			Namespace = _namespace;
			Name = name;

			Schema = procedure.Schema;
			IsStoredProcedure = true;
			StoredProcedure = procedure.Name;
			SqlScript = procedure.TextBody;

			int parCount = procedure.Parameters.Count;
			Parameters = new Parameter[parCount];
			for(int i = 0; i < parCount; i++) {
				Parameters[i] = new Parameter();
				StoredProcedureParameter par = procedure.Parameters[i];

				Parameters[i].Name = par.Name;
				Parameters[i].TypeName = par.DataType.Name;
				Parameters[i].Direction = par.IsOutputParameter ? ParameterDirection.InputOutput : ParameterDirection.Input;

				string pname = par.Name.Replace("[", string.Empty).Replace("@", string.Empty).Replace("]", string.Empty);
				var ph = PropertyHelper.CreatePropertyHelper(procedure.Parent, pname, par.DataType, true, Parameters[i].Direction);
				Parameters[i].PropertyName = ph.Name;
				Parameters[i].PropertyTypeName = ph.TypeName;
				Parameters[i].PropertyAttribute = ph.Attribute;
			}
		}
	}
}
